#define MM_MAP_VOTE_INCLUDED 1


#if !defined MM_GLOBALS_INCLUDED
#include "include/mm_globals.inl"
#endif

#if !defined MM_NOMS_INCLUDED
#include "include/mm_noms.inl"
#endif


#define MAX_MAPS 5
#define MAX_RECENT_MAPS 10
#define TASK_MAP_VOTE 3000


//{ CVARS
new gCvarMapVoteWin;
new gCvarMapVoteWinPercent;
new gCvarMapVoteDelay;
new gCvarMapsCount;
new gCvarMapVoteTime;
new gCvarRandomCheckMin;
new gCvarRandomCheckMax;
new gCvarRandomCheckLastMaps;
new gCvarMapVoteResults;
//}

new gMAP_VOTE_MENU;
new mapVoteEnd;

new mapsCount;
new maps[MAX_MAPS];
new mapsVotes[MAX_MAPS];
new playerVotedForMap[MAX_PLAYERS];
new isSecondMapVote;
new isMapMenuVisible;

stock plugin_init_mapVote(){
	gCvarMapVoteWin = register_cvar("mm_map_vote_win", "1");
	gCvarMapVoteWinPercent = register_cvar("mm_map_vote_win_percent", "50");
	gCvarMapVoteDelay = register_cvar("mm_map_vote_delay", "15");
	gCvarMapVoteTime = register_cvar("mm_map_vote_time", "20");
	gCvarMapsCount = register_cvar("mm_maps", "5");
	gCvarRandomCheckMin = register_cvar("mm_random_check_min", "1");
	gCvarRandomCheckMax = register_cvar("mm_random_check_max", "1");
	gCvarRandomCheckLastMaps = register_cvar("mm_random_last_maps", "6");
	gCvarMapVoteResults =  register_cvar("mm_map_results", "1");
	
	register_clcmd("say listmaps", "listmaps");
	register_clcmd("listmaps", "listmaps");
	
	register_clcmd("say recent", "saidRecentMaps");
	register_clcmd("say recentmaps", "saidRecentMaps");
	
	register_clcmd("recent", "saidRecentMaps");
	register_clcmd("recentmaps", "saidRecentMaps");
}


stock client_connect_mapVote(id) {
	playerVotedForMap[id] = PLAYER_DID_NOT_VOTE;
	if(isMapMenuVisible){
		menu_display(id, gMAP_VOTE_MENU);
	}
}

stock client_disconnect_mapVote(id){
	if(isMapMenuVisible){
		new itemId = playerVotedForMap[id];
		if(itemId != PLAYER_DID_NOT_VOTE  && itemId!= PLAYER_VOTE_EXIT){
			mapsVotes[itemId]--;
		}
	}
	playerVotedForMap[id] = PLAYER_DID_NOT_VOTE;
}

stock roundStart_mapVote() {
	if(isLastRound() && !gMapVoteStarted){
		set_pcvar_float(gCvarMP_TIMELIMIT, (get_gametime() + getSecondsToMapEnd() + getRoundTimeSeconds()+5 ) /  60.0);
		showFirstDelayedMapVote();
	}
}

public saidRecentMaps(id){
	if(!get_pcvar_num(gCvarActive))
		return PLUGIN_CONTINUE;
	client_print(id, print_console, "%L", LANG_PLAYER, "RECENT_MAPS");
	new count  = MAX_RECENT_MAPS;
	new c = 0;
	
	if(count){
		new key[16];
		new map[MAP_NAME_LEN];
		new timestamp;
		for(new i=0;i<count;i++){
			formatex(key, 15, "%s%d", keyLastPlayed, i);
			if(nvault_lookup(gVault, key, map, MAP_NAME_LEN -1, timestamp)) {
				client_print(id, print_console, "%d %s", i+1, map);
				c=1;
			} else {
				break;
			}
		}
	}
	if(c){
		client_print(id, print_chat, "%L", LANG_PLAYER ,"RECENT_MAPS_IN_CONSOLE");
	} else {
		client_print(id, print_chat, "%L", LANG_PLAYER, "NO_RECENT_MAPS");
	}
	return PLUGIN_HANDLED;
}
public listmaps(id){
	if(!get_pcvar_num(gCvarActive))
		return PLUGIN_CONTINUE;
	
	if(gAllMapsCount){
		client_print(id, print_console, "%L", LANG_PLAYER, "MAPS_COUNT", gAllMapsCount);
		new map[MAP_NAME_LEN];
		new mapRealName[MAP_NAME_LEN];
		new minP, maxP, mapId;
		new minPs[4];
		new maxPs[4];
		
		new msg[] = "%s %L:  Min:%s   Max:%s";
		new any[16];
		formatex(any, charsmax(any), "%L", LANG_PLAYER, "NOT_SPECIFIED");
		
		
		for(new i=0;i<gAllMapsCount;i++){
			if(!is_user_connected(id))
				break;
			if(getMapNameById(i, map)){
				isMapValid(map, 0,0,0, mapId, mapRealName, minP, maxP);
				num_to_str(minP, minPs, charsmax(minPs));
				num_to_str(maxP, maxPs, charsmax(maxPs));
				add(map, MAP_NAME_LEN -1, "     ");
				client_print(id, print_console, msg, map, LANG_PLAYER, "PLAYERS_COUNT", minP?minPs:any, maxP?maxPs:any);
			}
		}
		client_print(id, print_chat, "%L", LANG_PLAYER, "PRINT_LISTMAPS");
	}
	return PLUGIN_HANDLED;
}

//{ First map vote
public showFirstDelayedMapVote(){
	if(task_exists(TASK_MAP_CHANGE))
		remove_task(TASK_MAP_CHANGE);
		
	gMapVoteStarted = 1;
	
	getFirstVoteMaps();
	createMapsMenu();
	new delay = get_pcvar_num(gCvarMapVoteDelay);
	
	set_hudmessage(0, 0, 255, -1.0, 0.35, 0, 6.0, 5.0);
	ShowSyncHudMsg(0, gHudCenteredMsg, "%L", LANG_PLAYER, "VOTE_FOR_NEXT_MAP_IN", delay);
	if (delay > 5)
		set_task(float(delay -5), "speakTimeToChoose", 5);
	else 
		speakTimeToChoose(delay);
	set_task(float(delay), "mapVote");
}

stock getFirstVoteMaps(){
	new maxMaps = min(get_pcvar_num(gCvarMapsCount), MAX_MAPS);
	new nomsCount;
	getNominatedMaps(maps, maxMaps, nomsCount);
	if(nomsCount < maxMaps){
		addRandomMaps(maxMaps);
	}
}

stock addRandomMaps(maxMaps){
	new Array:randomMaps = ArrayCreate();
	new checkMin = get_pcvar_num(gCvarRandomCheckMin);
	new checkMax = get_pcvar_num(gCvarRandomCheckMax);
	new checkLast = get_pcvar_num(gCvarRandomCheckLastMaps);
	getRandomMaps(randomMaps, checkMin, checkMax, checkLast);
	new map;
	while(maxMaps > mapsCount  && ArraySize(randomMaps)){
		map = random(ArraySize(randomMaps));
		maps[mapsCount] = ArrayGetCell(randomMaps, map);
		ArrayDeleteItem(randomMaps, map);
		mapsCount++;
	}
	if(maxMaps > mapsCount && ArraySize(randomMaps) ==0) {
		if(checkLast) {
			checkLast = 0;
		} else {
			checkMin = 0;
			checkMax = 0;
		}
		getRandomMaps(randomMaps, checkMin, checkMax, checkLast);
		while(maxMaps > mapsCount && ArraySize(randomMaps) >0){
			map = random(ArraySize(randomMaps));
			maps[mapsCount] = ArrayGetCell(randomMaps, map);
			ArrayDeleteItem(randomMaps, map);
			mapsCount++;
		}
	}
	if(maxMaps > mapsCount && ArraySize(randomMaps) ==0) {
		getRandomMaps(randomMaps, 0, 0, 0);
		while(maxMaps > mapsCount && ArraySize(randomMaps) >0){
			map = random(ArraySize(randomMaps));
			maps[mapsCount] = ArrayGetCell(randomMaps, map);
			ArrayDeleteItem(randomMaps, map);
			mapsCount++;
		}
	}
	ArrayDestroy(randomMaps);
}


//}

//{ Second Map Vote Menu
public showSecondDelayedMapVote() {
	for(new i=0;i<MAX_PLAYERS;i++){
		playerVotedForMap[i] = PLAYER_DID_NOT_VOTE;
	}
	getSecondVoteMaps();
	createMapsMenu();
	set_task(5.0, "speakTimeToChoose", 5);
	set_task(10.0, "mapVote", TASK_MAP_VOTE);
	set_hudmessage(0, 0, 255, -1.0, 0.35, 0, 6.0, 5.0);
	ShowSyncHudMsg(0, gHudCenteredMsg, "%L", LANG_PLAYER, "VOTING_FAILED_NEXT_IN_TEN");
}

stock getSecondVoteMaps(){
	new itm1 = -1, itm1count=-1, idx1, idx2, itm2=-1,itm2count=-1;
	
	getTop2(maps, mapsVotes, mapsCount, itm1, idx1,itm1count,itm2,idx2, itm2count);
	
	for(new i=0;i<mapsCount;i++) {		
		mapsVotes[i] = 0;
		maps[i] = NO_MAP;
	}
	
	maps[0] = itm1;
	maps[1] = itm2;
	mapsCount = 2;
}
//}

stock createMapsMenu(){
	new title[32];
	formatex(title, charsmax(title), "%L", LANG_PLAYER, "TITLE_MAP_VOTE");
	gMAP_VOTE_MENU = menu_create(title, "handleMapVote");
	new mapName[MAP_NAME_LEN];
	
	new map;
	new itm[2];
	for(new i=0;i<mapsCount;i++){
		map = maps[i];
		itm[0] = i;
		getMapNameById(map, mapName);
		menu_additem(gMAP_VOTE_MENU, mapName, itm);
	}
}
public mapVote(){
	mapVoteEnd = 0;
	new players[32];
	new num;
	get_players(players, num, "ch");
	
	for(new i=0;i<num;i++) {
		menu_display(players[i], gMAP_VOTE_MENU);
	}
	isMapMenuVisible = 1;
	new Float:delay = get_pcvar_float(gCvarMapVoteTime);
	set_task(delay, "mapVoteEnded");
}
public mapVoteEnded() {
	mapVoteEnd = 1;
	new num;
	new players[32];
	get_players(players, num, "ch");
			
	isMapMenuVisible =  0;
	new map = -1;
	
	if(isSecondMapVote){
		if(mapsVotes[1] > mapsVotes[0]){
			map = maps[1];
		} else {
			map = maps[0];
		}
	} else {
		new itm =maps[0];
		new itmcount=mapsVotes[0];
		new sum = itm*itmcount;
		for(new i =1;i<mapsCount;i++){
			sum += mapsVotes[i] * maps[i];
			if(mapsVotes[i]>itmcount){
				itm = maps[i];
				itmcount = mapsVotes[i];
			}
		}
		new type = get_pcvar_num(gCvarMapVoteWin);
		switch(type){
			case 0:
			map = itm;
			case 1:{
				new percent = get_pcvar_num(gCvarMapVoteWinPercent);
				new minVotes =  floatround(float( num * percent)/100.0);
				if(itmcount>= minVotes){
					map = itm;
				}
			}
		}
	}
	for(new i=0;i<num;i++)
		menu_cancel(players[i]);
	menu_destroy(gTIME_VOTE_MENU);
	
	if(map > -1) {
		new mapName[MAP_NAME_LEN];
		getMapNameById(map, mapName);
		copy(gNextMap, MAP_NAME_LEN-1, mapName);
		set_pcvar_float(gCvarMP_TIMELIMIT, (get_gametime() + getSecondsToRoundEnd() + 5) / 60.0);
		
		client_print(0, print_chat, "%L", LANG_PLAYER, "NEXT_MAP_WILL_BE", mapName);
	} else {
		isSecondMapVote = 1;
		showSecondDelayedMapVote();
	}
}

public handleMapVote(id, menu, item) {
	if(playerVotedForMap[id] == PLAYER_DID_NOT_VOTE){		
		if(mapVoteEnd) {
			client_print(id, print_chat, "%L", LANG_PLAYER, "VOTE_END");
		}  else {
			new name[MAX_NAME_LEN];
			get_user_name(id, name, MAX_NAME_LEN -1);
			new itemId;
			if(item != MENU_EXIT){
				new acc, callback;
				new info[2];
				menu_item_getinfo(menu, item, acc, info, 1, _, _, callback);				
				new mapName[MAP_NAME_LEN];
				
				itemId = info[0];
				playerVotedForMap[id] = itemId;
				getMapNameById(maps[itemId], mapName);
				
				client_print(0, print_chat, "%L", LANG_PLAYER, "MAP_CHOOSEN",name,  mapName);
				mapsVotes[itemId]++ ;
			} else {
				client_print(0, print_chat, "%L", LANG_PLAYER, "PLAYER_NOT_VOTING", name);
				playerVotedForMap[id] = PLAYER_VOTE_EXIT;
			}
		}
	}
}

public showMapVoteResults(){
	
	new t;
	new msg[256];
	new item[MAP_NAME_LEN + 6];
	new result = get_pcvar_num(gCvarMapVoteResults);
	new mapName[MAP_NAME_LEN];
	switch(result){
		case 0: return;
		case 1:{
			for(new i=0;i<mapsCount;i++){
				t = maps[i];
				getMapNameById(t, mapName);
				formatex(item, charsmax(item), "%s [%d]^n", mapName, mapsVotes[i]);
				add(msg, charsmax(msg), item);
			}
		}
		case 2: {
			new itm1 = -1, itm1count=-1, idx1, idx2, itm2=-1,itm2count=-1;
			getTop2(maps, mapsVotes, mapsCount, itm1, idx1,itm1count,itm2,idx2, itm2count);
	
			getMapNameById(itm1, mapName);
			formatex(item, charsmax(item), "%s [%d]^n", mapName,  itm1count);
			add(msg, charsmax(msg), item);
			
			getMapNameById(itm2, mapName);
			formatex(item, charsmax(item), "%s [%d]", mapName,  itm2count);
			add(msg, charsmax(msg), item);
		}		
	}
	trim(msg);
	set_hudmessage(255, 0, 0, 0.01, 0.14, 0, 6.0, 1.0);
	ShowSyncHudMsg(0, gHudCenteredMsg,  msg);
	
	if(!mapTimeVoteEnd){
		set_task(0.5, "showMapVoteResults");
	}
}

stock isMapInVoteList(mapId){
	for(new i=0;i<mapsCount;i++)
		if(maps[i] == mapId)
			return 1;
	return 0;
}

stock getRandomMaps(Array:availableMaps, checkMin, checkMax, checkLastPlayed){
	new map[MAP_NAME_LEN];
	new mapId;
	new mapRealName[MAP_NAME_LEN];
	new minP, maxP;
	new valid;
	for(new i=0;i<gAllMapsCount;i++){
		if(isMapInVoteList(i))
			continue;
		if(checkMin || checkMax || checkLastPlayed) {
			if(getMapNameById(i, map)){
				valid = isMapValid(map, checkMin, checkMax, checkLastPlayed, mapId, mapRealName, minP, maxP);
				switch(valid){
					case MAP_VALID_FOR_NOMINATION:
					{
						if(!doArrayContain(availableMaps, i))
							ArrayPushCell(availableMaps, i);
					}
				}
			}			
		} else  {
			if(!doArrayContain(availableMaps, i) )
				ArrayPushCell(availableMaps, i);		
		}
	}
}


stock doArrayContain(Array:which, item) {
	new count = ArraySize(which);
	for(new i=0;i<count;i++){
		if(ArrayGetCell(which, i) == item)
			return 1;
	}
	return 0;
}
